package com.xrui.hbase;


import com.xrui.hbase.schema.TableLayout;
import com.xrui.hbase.util.ReferenceCountable;

/**
 * The Table interface provides operations on Tables. To perform reads to and
 * writes from a HBase table use a {@link TableReader} or {@link TableWriter}.
 * Instances of these classes can be obtained by using the {@link #openTableReader()}
 * and {@link #openTableWriter()} methods.  {@link EntityId}s, which identify particular
 * rows within a HBase table are also generated from its components.
 * <p>
 * <h2>HBaseTable instance lifecycle:</h2>
 * <p>
 * To open a connection to a HBaseTable, use {@link HBase#openTable(String)}. A HBaseTable
 * contains an open connection to an HBase cluster. Because of this, HBaseTable objects
 * must be released using {@link #release()} when finished using it:
 * </p>
 * <pre>
 *   <code>
 *     final HBaseTable table = myHBase.openTable("tableName");
 *     // Do some magic
 *     table.release();
 *   </code>
 * </pre>
 * <p>
 * <h2>Reading and Writing from a HBaseTable:</h2>
 * <p>
 * The HBaseTable interface does not directly provide methods to perform I/O on a HBase
 * table. Read and write operations can be performed using either a {@link TableReader}
 * or a {@link TableWriter}:
 * </p>
 * <pre>
 *   <code>
 *     final HBaseTable table = myHBase.openTable("tableName");
 *
 *     final EntityId myId = table.getEntityId("myRowKey");
 *
 *     final TableReader reader = table.openTableReader();
 *     final TableWriter writer = table.openTableWriter();
 *
 *     // Read some data from a HBase table using an existing EntityId and HBaseDataRequest.
 *     final HBaseRowData row = reader.create(myId, myDataRequest);
 *
 *     // Do things with the row...
 *
 *     // Write some data to a new column in the same row.
 *     writer.put(myId, "info", "newColumn", "newValue");
 *
 *     // Close open connections.
 *     reader.close();
 *     writer.close();
 *     table.release();
 *   </code>
 * </pre>
 *
 * @see TableReader for more information about reading data from a HBase table.
 * @see TableWriter for more information about writing data to a HBase table.
 * @see EntityId for more information about identifying rows with entity ids.
 * @see HBase for more information about opening a HBaseTable instance.
 */
public interface Table extends ReferenceCountable<Table> {
    /**
     * @return the HBase instance this table belongs to.
     */
    HBase getHBase();

    /**
     * @return the name of this table.
     */
    String getName();

    /**
     * @return the URI for this table, trimmed at the table path component.
     */
    HBaseURI getURI();

    /**
     * @return the layout of this table.
     */
    TableLayout getLayout();

    /**
     * Creates an entity id from a list of components.
     *
     * @param rowKey This can be one of the following depending on row key encoding:
     *               <ul>
     *               <li>
     *               Raw, Hash, Hash-Prefix EntityId: A single String or byte array
     *               component.
     *               </li>
     *               <li>
     *               Formatted EntityId: The primitive row key components (string, int,
     *               long) either passed in their expected order in the key or as an ordered
     *               list of components.
     *               </li>
     *               </ul>
     * @return a new EntityId with the specified HBase row key.
     */
    EntityId getEntityId(Object... rowKey) throws java.io.IOException;


    EntityId getEntityIdFromRowKey(byte[] rowKey) throws java.io.IOException;

    /**
     * Opens a TableReader for this table.
     * <p>
     * <p>
     * This method is equivalent to <code>getReaderFactory().readerBuilder().build()</code>. It sets
     * all options to their default values.
     * </p>
     * <p>
     * <p> The caller of this method is responsible for closing the returned reader. </p>
     * <p> The reader returned by this method does not provide any isolation guarantee.
     * In particular, you should assume that the underlying resources (connections, buffers, etc)
     * are used concurrently for other purposes. </p>
     *
     * @return A TableReader for this table.
     */
    TableReader openTableReader();

    /**
     * Opens a TableWriter for this table.
     * <p>
     * <p> The caller of this method is responsible for closing the returned writer.</p>
     * <p> The writer returned by this method does not provide any isolation guarantee.</p>
     * In particular, you should assume that the underlying resources (connections, buffers, etc)
     * are used concurrently for other purposes.
     *
     * @return A TableWriter for this table.
     */
    TableWriter openTableWriter();

    /**
     * Opens a BufferedWriter for this table.
     *
     * @return A BufferedWriter for this table.
     */
    BufferedWriter openBufferedWriter();
}
